import express, { RequestHandler, Express } from 'express';
import { ViteDevServer } from 'vite';
import {
  loadSsrEntryModule,
  matchPageUrl,
  resolveTemplatePath,
  isProd,
  cwd,
} from './util';
import { renderToString } from 'react-dom/server';
import React from 'react';
import * as fs from 'fs';
import { User } from '../entry-server';
import serveStatic from 'serve-static';
import path from 'path';
import { performance, PerformanceObserver } from 'perf_hooks';
import Helmet from 'react-helmet';

// 初始化监听器逻辑，用于性能监控
const perfObserver = new PerformanceObserver((items) => {
  items.getEntries().forEach((entry) => {
    console.log('[performance]', entry.name, entry.duration.toFixed(2), 'ms');
  });
  performance.clearMarks();
});
perfObserver.observe({ entryTypes: ['measure'] });

/**
 * 创建 vite ssr 中间件
 */
async function createSsrMiddleware(app: Express): Promise<RequestHandler> {
  let vite: ViteDevServer | null = null;

  if (!isProd) {
    // 处于开发环境时，创建 vite 开发服务器
    vite = await (
      await import('vite')
    ).createServer({
      root: process.cwd(),
      server: {
        middlewareMode: 'ssr',
      },
    });

    // 注册 Vite Middlewares，主要用来处理客户端资源
    app.use(vite.middlewares);
  }

  return async (req, res, next) => {
    try {
      const { originalUrl } = req;

      if (!matchPageUrl(originalUrl)) {
        // 当前请求的是静态资源，则不进行处理
        return next();
      }

      //* 1.加载服务端入口组件模块
      const { serverEntry, fetchData } = await loadSsrEntryModule(vite);

      //* 2.数据预取
      const data: User = await fetchData();

      //* 3.渲染服务端组件，转换为 HTML 字符串
      performance.mark('render-start');
      const appHtml = renderToString(
        React.createElement(serverEntry, { data })
      );
      performance.mark('render-end');
      performance.measure('renderToString', 'render-start', 'render-end');
      // 生成 <head> 标签的内容
      const helmet = Helmet.renderStatic();

      //* 4.拼接完整的 HTML 字符串返回给客户端
      const templatePath = resolveTemplatePath();
      let template = fs.readFileSync(templatePath, 'utf-8');
      if (!isProd && vite) {
        // 当前环境为开发环境
        // 所以需要注入 HMR、环境变量相关的代码
        template = await vite.transformIndexHtml(originalUrl, template);
      }
      const html = template
        .replace('<!-- SSR_APP_TITLE -->', helmet.title.toString())
        .replace('<!-- SSR_APP -->', appHtml)
        // 注入数据标签，用于客户端注水
        .replace(
          '<!-- SSR_DATA -->',
          `<script>window.__SSR_DATA__=${JSON.stringify(data)}</script>`
        );

      res.status(200).setHeader('Content-Type', 'text/html').end(html);
    } catch (error: any) {
      vite?.ssrFixStacktrace(error);
      console.error(error);
      res.status(500).end(error.message);
    }
  };
}

async function createServer() {
  const app = express();

  // 加入 vite ssr 中间件
  app.use(await createSsrMiddleware(app));

  // 用于处理静态资源
  if (isProd) {
    app.use(serveStatic(path.join(cwd, 'dist/client')));
  }

  app.listen(5004, () => {
    console.log('服务器已启动');
    console.log('http://localhost:5004');
  });
}

createServer();
